<?php
/**
 * @describe 阿里云文件上传封装工具类
 *
 * @author wlx
 * @since 2018/11/2
 */

namespace App\Services;

use Exception;
use DateTime;
use finfo;
use Illuminate\Support\Facades\Config;
use JohnLui\AliyunOSS;

class OssTool
{
    /* 城市名称：
         *
         *  经典网络下可选：杭州、上海、青岛、北京、张家口、深圳、香港、硅谷、弗吉尼亚、新加坡、悉尼、日本、法兰克福、迪拜
         *  VPC 网络下可选：杭州、上海、青岛、北京、张家口、深圳、硅谷、弗吉尼亚、新加坡、悉尼、日本、法兰克福、迪拜
         */

    // 经典网络 or VPC
    private $city = '北京';
    // 经典网络 or VPC
    private $networkType = '经典网络';

    private $accessKeyId = '';
    private $accessKeySecret = '';


    private $ossClient;
    const BUCKET_NAME = 'xiabuy';

    /**
     * OSS constructor.
     * 私有初始化 API，非 API，不用关注
     *
     * @param bool $isInternal 是否使用内网
     *
     * @throws Exception
     */
    public function __construct($isInternal = false)
    {
        if ($this->networkType == 'VPC' && !$isInternal) {
            throw new Exception("VPC 网络下不提供外网上传、下载等功能");
        }
        $this->city = Config::get('alioss.city');
        $this->networkType = Config::get('alioss.networkType');
        $this->accessKeyId = Config::get('alioss.accessKeyId');
        $this->accessKeySecret = Config::get('alioss.accessKeySecret');
        $this->ossClient = AliyunOSS::boot(
            $this->city,
            $this->networkType,
            $isInternal,
            $this->accessKeyId,
            $this->accessKeySecret
        );
    }


    /**
     *使用外网上传文件
     *
     * @param  string $bucketName bucket名称
     * @param $ossKey
     * @param $filePath
     * @param array $options 中传入参数ContentType，方便获取静态资源
     * ['ContentType'=>mime_content_type($filePath) ]
     *
     * @return mixed
     */
    public static function publicUpload($bucketName, $ossKey, $filePath, $options = [])
    {
        $oss = new self();
        if (empty($bucketName)) {
            $bucketName = self::BUCKET_NAME;
        }
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->uploadFile($ossKey, $filePath, $options);
    }

    /**
     *使用阿里云内网上传文件
     *
     * @param  string bucket名称
     * @param  string 上传之后的 OSS object 名称
     * @param  string 上传文件路径
     *
     * @return \Aliyun\OSS\Models\PutObjectResult
     */
    public static function privateUpload($bucketName, $ossKey, $filePath, $options = [])
    {
        $oss = new self(true);
        if (empty($bucketName)) {
            $bucketName = self::BUCKET_NAME;
        }
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->uploadFile($ossKey, $filePath, $options);
    }


    /***
     * @param $bucketName
     * @param $ossKey 存储的文件名
     * @param $content
     * @param array $options
     *
     * @return \Aliyun\OSS\Models\PutObjectResult
     */
    public static function publicUploadContent($bucketName, $ossKey, $content, $options = [])
    {
        $oss = new self();
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->uploadContent($ossKey, $content, $options);
    }

    /**
     * 使用阿里云内网直接上传变量内容
     *
     * @param  string bucket名称
     * @param  string 上传之后的 OSS object 名称
     * @param  string 上传的变量
     *
     * @return boolean 上传是否成功
     */
    public static function privateUploadContent($bucketName, $ossKey, $content, $options = [])
    {
        $oss = new self(true);
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->uploadContent($ossKey, $content, $options);
    }


    /**
     * 使用外网删除文件
     *
     * @param  string bucket名称
     * @param  string 目标 OSS object 名称
     *
     * @return boolean 删除是否成功
     */
    public static function publicDeleteObject($bucketName, $ossKey)
    {
        $oss = new self();
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->deleteObject($bucketName, $ossKey);
    }

    /**
     * 使用阿里云内网删除文件
     *
     * @param  string bucket名称
     * @param  string 目标 OSS object 名称
     *
     * @return boolean 删除是否成功
     */
    public static function privateDeleteObject($bucketName, $ossKey)
    {
        $oss = new self(true);
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->deleteObject($bucketName, $ossKey);
    }


    /**
     * -------------------------------------------------
     *
     *
     *  下面不再分公网内网出 API，也不注释了，大家自行体会吧。。。
     *
     *
     * -------------------------------------------------
     */

    public function copyObject($sourceBuckt, $sourceKey, $destBucket, $destKey)
    {
        $oss = new self();
        return $oss->ossClient->copyObject($sourceBuckt, $sourceKey, $destBucket, $destKey);
    }

    public function moveObject($sourceBuckt, $sourceKey, $destBucket, $destKey)
    {
        $oss = new self();
        return $oss->ossClient->moveObject($sourceBuckt, $sourceKey, $destBucket, $destKey);
    }

    // 获取公开文件的 URL
    public static function getPublicObjectURL($bucketName = '', $ossKey)
    {
        $oss = new self();
        if (empty($bucketName)) {
            $bucketName = self::BUCKET_NAME;
        }
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->getPublicUrl($ossKey);
    }

    // 获取私有文件的URL，并设定过期时间，如 \DateTime('+1 day')
    public static function getPrivateObjectURLWithExpireTime($bucketName, $ossKey, DateTime $expire_time)
    {
        $oss = new self();
        $oss->ossClient->setBucket($bucketName);
        return $oss->ossClient->getUrl($ossKey, $expire_time);
    }

    public static function createBucket($bucketName)
    {
        $oss = new self();
        return $oss->ossClient->createBucket($bucketName);
    }

    public static function getAllObjectKey($bucketName)
    {
        $oss = new self();
        return $oss->ossClient->getAllObjectKey($bucketName);
    }

    public static function getObjectMeta($bucketName, $ossKey)
    {
        $oss = new self();
        return $oss->ossClient->getObjectMeta($bucketName, $ossKey);
    }

    /***
     * 简单配置上传文件$options
     *
     * @param $filePath
     *
     * @return array
     */
    public static function getContentTypeOptionsByFilePath($filePath)
    {
        $fi = new finfo(FILEINFO_MIME_TYPE);
        $mime_type = $fi->file($filePath);
        return [
            'ContentType' => $mime_type,
        ];
    }

}